package com.zhangzhan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangzhan.constants.SystemConstants;
import com.zhangzhan.domain.commcon.App;
import com.zhangzhan.domain.commcon.ResponseResult;
import com.zhangzhan.domain.dto.*;
import com.zhangzhan.domain.entity.Article;
import com.zhangzhan.domain.entity.ArticleTag;
import com.zhangzhan.domain.entity.Category;
import com.zhangzhan.domain.vo.ArticleListVO;
import com.zhangzhan.domain.vo.ArticleSelectByIdVO;
import com.zhangzhan.domain.vo.HotArticleVO;
import com.zhangzhan.domain.vo.PageVO;
import com.zhangzhan.mapper.ArticleMapper;
import com.zhangzhan.service.ArticleService;
import com.zhangzhan.service.ArticleTagService;
import com.zhangzhan.service.CategoryService;
import com.zhangzhan.service.MenuService;
import com.zhangzhan.utils.BeanCopyUtils;
import com.zhangzhan.utils.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 张一恒
 * @version 1.0
 * 文章表
 */
@Service
@Slf4j
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
    //@Autowired
    //private ArticleMapper articleMapper;
    @Autowired
    CategoryService categoryService;
    @Autowired
    RedisCache redisCache;

    @Autowired
    private ArticleTagService articleTagService;

    @Autowired
    private MenuService menuService;

    @Override
    public ResponseResult hotArticle() {
        //查询浏览量前10的文章
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        //不显示草稿
        wrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL)
                //不能把删除的文章查出来
                .eq(Article::getDelFlag, SystemConstants.ARTICLE_STATUS_NORMAL)
                //根据访问量降序排序
                .orderByDesc(Article::getViewCount);

        //最多显示10条,可以分页查询
        Page<Article> articlePage = new Page<>(1, 10);
        //调mapper查数据库
        Page<Article> selectPage = this.getBaseMapper().selectPage(articlePage, wrapper);
        //取page当前页的每一条记录
        List<Article> records = selectPage.getRecords();

        //使用vo来返回参数信息
        //copy数据
        List<HotArticleVO> vos = BeanCopyUtils.beanCopyUtil(records, HotArticleVO.class);

        //返回
        return ResponseResult.okResult(vos);
    }

    //文章分页查询
    @Override
    public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) {
        //根据分类查询对应的文章
        LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
        articleWrapper.
                eq(!Objects.isNull(categoryId) && categoryId != 0, Article::getCategoryId, categoryId)
                //不是草稿
                .eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL)
                //置顶内容排在第一位
                .orderByDesc(Article::getIsTop);

        //分页
        Page<Article> articlePage = new Page<>(pageNum, pageSize);
        Page<Article> page = this.page(articlePage, articleWrapper);
        //封装到vo
        List<Article> records = page.getRecords();

        //设置分类名称
        for (Article record : records) {
            Category category = categoryService.getById(record.getCategoryId());
            record.setCategoryName(category.getName());
        }

        List<ArticleListVO> vo = BeanCopyUtils.beanCopyUtil(records, ArticleListVO.class);

        PageVO pageVO = new PageVO(vo, page.getTotal());

        return ResponseResult.okResult(pageVO);
    }

    //文章详情
    @Override
    public ResponseResult selectById(Long id) {

        Article article = this.lambdaQuery()
                .eq(Objects.nonNull(id) && id != SystemConstants.ARTICLE_STATUS_NORMAL, Article::getId, id)
                .one();
        Category category = categoryService.getById(article.getCategoryId());
        article.setCategoryName(category.getName());


        Integer value = redisCache.getCacheMapValue(App.ARTICLE_VIEWCOUNT, id.toString());
        article.setViewCount(value.longValue());

        ArticleSelectByIdVO vo = BeanCopyUtils.beanCopyUtils(article, ArticleSelectByIdVO.class);

        return ResponseResult.okResult(vo);

    }

    /**
     * @param id
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @description 更新文章浏览量
     * @author 31115
     * @date 2022/12/4 21:35
     */
    @Override
    public ResponseResult updateViewCount(Long id) {
        //更新浏览量时 是更新redis里的数据
        //每次访问文章加1
        redisCache.incrementCacheMapValue(App.ARTICLE_VIEWCOUNT, id.toString(), 1);
        return ResponseResult.okResult();
    }

    /**
     * @param addArticleDto
     * @return void
     * @description 新增博文
     * @author 31115
     * @date 2022/12/6 17:13
     */
    @Override
    @Transactional
    public ResponseResult addArticle(AddArticleDto addArticleDto) {
        //状态等于1 表示发布 0表示存入草稿
        Article article = new Article();
        if ("1".equals(addArticleDto.getStatus())) {
            //发布
            BeanUtils.copyProperties(addArticleDto, article, "tags");
            save(article);
        } else if ("0".equals(addArticleDto.getStatus())) {
            BeanUtils.copyProperties(addArticleDto, article, "tags");
            save(article);
        }

        //插入中间表
        List<Long> tags = addArticleDto.getTags();
        List<ArticleTag> articleTagList = tags.stream()
                .map(tagId -> new ArticleTag(article.getId(), tagId))
                .collect(Collectors.toList());

        articleTagService.saveBatch(articleTagList);
        return ResponseResult.okResult();
    }

    /**
     * @param pageNum
     * @param pageSize
     * @param likeArticleDto
     * @return com.zhangzhan.domain.commcon.ResponseResult<com.zhangzhan.domain.vo.PageVO>
     * @description 分页查询
     * @author 31115
     * @date 2022/12/7 9:48
     */
    @Override
    public ResponseResult<PageVO> listArticle(Integer pageNum, Integer pageSize, LikeArticleDto likeArticleDto) {

        Page<Article> articlePage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(likeArticleDto.getTitle() != null, Article::getTitle, likeArticleDto.getTitle());
        wrapper.like(likeArticleDto.getSummary() != null, Article::getSummary, likeArticleDto.getSummary());
        page(articlePage,wrapper);
        List<Article> records = articlePage.getRecords();
        List<ListArticleDto> listArticleDtos = BeanCopyUtils.beanCopyUtil(records, ListArticleDto.class);

        return ResponseResult.okResult(new PageVO(listArticleDtos,articlePage.getTotal()));
    }

    /**
     * @description 修改回显数据
     * @param id
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/7 10:02
     */
    @Override
    public ResponseResult select(Long id) {
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(id!=null,Article::getId,id);
        Article article = getOne(wrapper);

        LambdaQueryWrapper<ArticleTag> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(ArticleTag::getArticleId,article.getId());
        List<ArticleTag> tags = articleTagService.list(wrapper1);
        List<Long> tagIds = tags.stream()
                .map(articleTag -> {
                    Long tagId = articleTag.getTagId();
                    return tagId;
                }).collect(Collectors.toList());

        RowBackArticleDto rowBackArticleDto = BeanCopyUtils.beanCopyUtils(article, RowBackArticleDto.class);
        rowBackArticleDto.setTags(tagIds);


        return ResponseResult.okResult(rowBackArticleDto);
    }

    /**
     * @description 修改博文
     * @param updateArticleDto
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/7 10:19
     */
    @Override
    @Transactional
    public ResponseResult updateArticle(UpdateArticleDto updateArticleDto) {

        //先全部删除文章标签表数据
        LambdaQueryWrapper<ArticleTag> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(updateArticleDto.getId()!=null,ArticleTag::getArticleId,updateArticleDto.getId());
        articleTagService.remove(wrapper);

        //修改文章内容
        Article article = BeanCopyUtils.beanCopyUtils(updateArticleDto, Article.class);
        updateById(article);

        //修改文章标签中间表
        List<Long> tags = updateArticleDto.getTags();
        List<ArticleTag> articleTags = tags.stream()
                .map(tagId -> new ArticleTag(article.getId(), tagId))
                .collect(Collectors.toList());
        articleTagService.saveBatch(articleTags);


        log.info("修改文章成功");

        return ResponseResult.okResult();
    }

    /**
     * @description 删除博文
     * @param id
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/7 10:39
     */
    @Override
    public ResponseResult deleteArticle(Long id) {
        //逻辑删除博文
        getBaseMapper().deleteArticle(id);
        return ResponseResult.okResult();
    }


}
